package com.fancy.application.tools.autoddl.service.Impl;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.fancy.application.framework.dic.method.Dict;
import com.fancy.application.framework.dic.model.DictionaryObj;
import com.fancy.application.framework.dic.model.DictionarySimpleFieldObj;
import com.fancy.application.tools.autoddl.constants.DataBaseTypeEnum;
import com.fancy.application.tools.autoddl.model.ColumnsModel;
import com.fancy.application.tools.autoddl.model.TableModel;
import com.fancy.application.tools.autoddl.service.IDatabaseTableManageService;
import lombok.extern.log4j.Log4j2;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@Log4j2
public abstract class DatabaseTableManageService implements IDatabaseTableManageService {

    protected DataBaseTypeEnum databaseType;
    /** 类型转换 */
    protected Map<String, String> javaTypeMap;

    //已经存在的表
    protected List<TableModel> tableModels;
    //所有已经存在的数据字典
    protected List<DictionaryObj> tableDictionaries;

    /**
     * 未创建的表的列表
     */
    protected List<TableModel> unCreateTableList;
    /**
     * 未字段的表的列表
     */
    protected List<TableModel> unAddedColumnList;




    @Resource
    private JdbcTemplate jdbcTemplate;

    public void createTables(){
        getTableInfo();
        getDict();
        compare();
        executeSql();
    }

    /**
     * 获取数据字典数据
     */
    protected  void getDict(){
        tableDictionaries = new ArrayList<>();
        Map<String, DictionaryObj> dictionaryMap = Dict.getInstance().getDictMap();
        tableDictionaries.addAll(dictionaryMap.values());
    }


    /**
     * 对比
     * 先比较没有的表，如果没有表，则直接新建表。
     * 如果已经存在表，再去比较字段、如果字段不存在，则新增字段
     * 因为考虑到有时候数据字典的字段长度和实际不一致的问题，暂时参考hibernate，字段长度不变
     *
     */
    protected  void compare(){
        unCreateTableList = new ArrayList<>();
        unAddedColumnList = new ArrayList<>();
        //新建的表
        tableDictionaries.forEach(dictionaryObj -> {
            if(StrUtil.isBlank(dictionaryObj.getTableName())||!dictionaryObj.isExist()){return;}
            Boolean d = getUnCreateTableList(dictionaryObj);
            if(d){
                TableModel tableModel = new TableModel();
                tableModel.setName(dictionaryObj.getTableName());
                dictionaryObj.getSimpleFieldList().forEach(dictionarySimpleFieldObj -> {
                    if(!dictionarySimpleFieldObj.isExist()){return;}
                    tableModel.getColumnsModelList().add(createColumnModel(dictionarySimpleFieldObj));
                });
                //tableModel.getColumnsModelList().add()
                unCreateTableList.add(tableModel);
                log.debug("待创建的表名为{}",dictionaryObj.getTableName());
            }
        });
        log.debug("待创建的表的数量为{}",unCreateTableList.size());
//        //需要新建的字段,先找到
        tableDictionaries.forEach(dictionaryObj -> {
            Boolean d = getCreatedTableList(dictionaryObj);
            if(d) {
                TableModel tableModel = new TableModel();
                tableModel.setName(dictionaryObj.getTableName());
                List<ColumnsModel> columnsModelList = getColumnsByTable(dictionaryObj.getTableName());  //获得所有的
                dictionaryObj.getSimpleFieldList().forEach(dictionarySimpleFieldObj -> {
                   //此处要计算新增的字段
                    boolean exist = columnsModelList.stream().noneMatch(columnsModel -> StrUtil.equals(dictionarySimpleFieldObj.getColumn(),columnsModel.getName()));
                    if(exist){
                        tableModel.getColumnsModelList().add(createColumnModel(dictionarySimpleFieldObj));
                    }
                });
                if(tableModel.getColumnsModelList().size()>0)
                    unAddedColumnList.add(tableModel);
            }
        });
        log.debug("需要新增字段的表数量为{}",unAddedColumnList.size());
    }

    private ColumnsModel createColumnModel(DictionarySimpleFieldObj dictionarySimpleFieldObj) {
        ColumnsModel columnsModel = new ColumnsModel();
        String columnName = dictionarySimpleFieldObj.getColumn();
        columnsModel.setName(columnName);
        Integer length = dictionarySimpleFieldObj.getLength();
        columnsModel.setLength(length);
        String columnType = dictionarySimpleFieldObj.getType().name();
        columnsModel.setColumnType(javaTypeMap.get(columnType));
        boolean pk = dictionarySimpleFieldObj.isPk();
        columnsModel.setPrimaryKey(pk);
        boolean nullable = dictionarySimpleFieldObj.isNullable();
        columnsModel.setNull(nullable);
        return columnsModel;
    }

    //是否存在未创建的表
    private Boolean getUnCreateTableList(DictionaryObj d){

        String tableName = d.getTableName();
        Optional<TableModel> optionalTableModel = tableModels.stream().filter(tableModel ->
                StrUtil.equals(tableModel.getName(),tableName)).findFirst();

        return !optionalTableModel.isPresent();
    }
    //获取存在的表
    private Boolean getCreatedTableList(DictionaryObj d){

        String tableName = d.getTableName();
        Optional<TableModel> optionalTableModel = tableModels.stream().filter(tableModel ->
                StrUtil.equals(tableModel.getName(),tableName)).findFirst();
        return optionalTableModel.isPresent();
    }

    private List<ColumnsModel> getColumnsByTable(String tableName){
        Optional<TableModel> optionalTableModel =  tableModels.stream().filter(tableModel ->
                StrUtil.equals(tableModel.getName(),tableName)).findFirst();
        return optionalTableModel.get().getColumnsModelList();
    }

    /**
     * 执行sql
     */
    protected  void executeSql(){
        //先执行建表语句
        List<String> sqlList = generateSql();
        if(sqlList!=null&&sqlList.size()>0){
            log.debug("开始建表...");
            this.jdbcTemplate.batchUpdate(ArrayUtil.toArray(sqlList,String.class));
            log.debug("建表结束...");
        }

    }

    protected abstract void getTableInfo();  //获取表结构
    protected abstract List<String> generateSql();  //生成建表sql

    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }

//    private Connection getConnection() throws SQLException {
//        return dataSource.getConnection();
//    }


}
